package cn.harry.wx.service.impl;

import cn.harry.wx.dao.WxMsgReplyRuleDao;
import cn.harry.wx.entity.WxMsgReplyRule;
import cn.harry.wx.service.WxMsgReplyRuleService;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalTime;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 自动回复规则
 *
 * @author honghh
 * Date 2021-04-08 16:19:27
 * Copyright (C) www.tech-harry.cn
 */
@Service("wxMsgReplyRuleService")
public class WxMsgReplyRuleServiceImpl extends ServiceImpl<WxMsgReplyRuleDao, WxMsgReplyRule> implements WxMsgReplyRuleService {


    @Override
    public IPage<WxMsgReplyRule> getPage(WxMsgReplyRule wxMsgReplyRule, Integer pageSize, Integer pageNum) {
        LambdaQueryWrapper<WxMsgReplyRule> wrapper = new LambdaQueryWrapper<>(wxMsgReplyRule);

        if (StrUtil.isNotEmpty(wxMsgReplyRule.getBeginTime())) {
            wrapper.gt(WxMsgReplyRule::getCreateTime, wxMsgReplyRule.getBeginTime());
        }
        if (StrUtil.isNotEmpty(wxMsgReplyRule.getEndTime())) {
            wrapper.lt(WxMsgReplyRule::getCreateTime, wxMsgReplyRule.getEndTime());
        }
        return page(new Page<>(pageNum, pageSize), wrapper);
    }


    @Override
    public WxMsgReplyRule selectById(Long id) {
        return this.baseMapper.selectById(id);
    }

    @Override
    public int create(WxMsgReplyRule wxMsgReplyRule) {
        return this.baseMapper.insert(wxMsgReplyRule);
    }


    @Override
    public int update(Long id, WxMsgReplyRule wxMsgReplyRule) {
        wxMsgReplyRule.setId(id);
        return this.baseMapper.updateById(wxMsgReplyRule);
    }


    @Override
    public int deleteByIds(Long[] ids) {
        return this.baseMapper.deleteBatchIds(Arrays.asList(ids));
    }


    /**
     * 筛选符合条件的回复规则
     *
     * @param appid      公众号appid
     * @param exactMatch 是否精确匹配
     * @param keywords   关键词
     * @return 规则列表
     */
    @Override
    public List<WxMsgReplyRule> getMatchedRules(String appid, boolean exactMatch, String keywords) {
        LocalTime now = LocalTime.now();
        return this.getValidRules().stream()
                // 检测是否是对应公众号的规则，如果appid为空则为通用规则
                .filter(rule -> !StringUtils.hasText(rule.getAppid()) || appid.equals(rule.getAppid()))
                // 检测是否在有效时段，effectTimeStart为null则一直有效
                .filter(rule -> null == rule.getEffectTimeStart() || rule.getEffectTimeStart().toLocalTime().isBefore(now))
                // 检测是否在有效时段，effectTimeEnd为null则一直有效
                .filter(rule -> null == rule.getEffectTimeEnd() || rule.getEffectTimeEnd().toLocalTime().isAfter(now))
                //检测是否符合匹配规则
                .filter(rule -> isMatch(exactMatch || rule.isExactMatch(), rule.getMatchValue().split(","), keywords))
                .collect(Collectors.toList());
    }

    /**
     * 获取当前时段内所有有效的回复规则
     *
     * @return
     */
    @Override
    public List<WxMsgReplyRule> getValidRules() {
        return this.baseMapper.selectList(
                new QueryWrapper<WxMsgReplyRule>()
                        .eq("status", 1)
                        .isNotNull("match_value")
                        .ne("match_value", "")
                        .orderByDesc("priority"));
    }


    /**
     * 检测文字是否匹配规则
     * 精确匹配时，需关键词与规则词语一致
     * 非精确匹配时，检测文字需包含任意一个规则词语
     *
     * @param exactMatch 是否精确匹配
     * @param ruleWords  规则列表
     * @param checkWords 需检测的文字
     * @return
     */
    public static boolean isMatch(boolean exactMatch, String[] ruleWords, String checkWords) {
        if (!StringUtils.hasText(checkWords)) {
            return false;
        }
        for (String words : ruleWords) {
            if (exactMatch && words.equals(checkWords)) {
                return true;//精确匹配，需关键词与规则词语一致
            }
            if (!exactMatch && checkWords.contains(words)) {
                return true;//模糊匹配
            }
        }
        return false;
    }
}